/**
 * 210325：修正updateCall中焦点的计算为矩阵计算，以修正绑定到旋转物体中焦点错误的bug
 * 210824：升级修改【three.js r120-r131】
 * 20220304:[require] to [import]...jordia
 */

import {Vector3,Matrix4} from 'three';

/**
 * 绑定相机控制到对象
 * 由于绑定目标和相机控制要在同一帧内完成更新，建议使用FrameQueue更新，
 * 并确保绑定目标先于相机更新（矩阵运算需要最新的绑定目标变换）
 */
export default class CameraBind {
    constructor(camCtr){
        this.cameraCtr=camCtr;
        this.init();
    }

    /**
     * 设置绑定对象
     * @param obj {Object3D}
     */
    set target(obj){
        this.bindTarget=obj;
    }

    /**
     * 获取用于更新的函数
     */
    get callback(){
        return this.updateCall.bind(this);
    }

    /**
     * 设置自定义更新函数
     * @param func
     */
    set onUpdate(func){
        this.customCall=func;
    }

    /**
     * 销毁
     */
    dispose(){
        this.cameraCtr.eventCenter.removeEventListener('change',this.cameraChangeHandle.bind(this));
        this.tV0=null;
        this.tarInv=null;
        this.camInv=null;
        this.cameraCtr=null;
        this.trsMat=null;
        this.tarVec=null;
        this.camWld=null;
        this.locCam=null;
        this.bindTarget=null;
    }

    init(){
        this.initVariable();
        this.initEventBind();
    }
    initVariable(){
        this.bindTarget=null;
        this.tV0=new Vector3();
        this.tarInv=new Matrix4();
        this.camWld=new Matrix4();
        this.locCam=new Matrix4();
        this.camInv=new Matrix4();
        this.trsMat=new Matrix4();
        this.tarVec=new Vector3();
        this.customCall=null;
    }
    initEventBind(){
        this.cameraCtr.eventCenter.addEventListener('change',this.cameraChangeHandle.bind(this));
    }

    /**
     * 相机更新句柄
     * @param e
     */
    cameraChangeHandle(e){
        this.cameraCtr.camera.updateMatrixWorld();
        // this.tarInv.getInverse(this.bindTarget.matrixWorld);20210824
        this.tarInv.copy(this.bindTarget.matrixWorld).invert();
        this.camWld.copy(this.cameraCtr.camera.matrixWorld);
        this.locCam.multiplyMatrices(this.tarInv,this.camWld);
        this.tarVec.copy(this.cameraCtr.target);
        this.tarVec.applyMatrix4(this.tarInv);
    }

    /**
     * 绑定跟随时的更新函数
     */
    updateCall(){
        this.cameraCtr.camera.updateMatrixWorld();
        // this.cameraCtr.camera.applyMatrix4(this.camInv.getInverse(this.cameraCtr.camera.matrixWorld));20210824
        this.cameraCtr.camera.applyMatrix4(this.camInv.copy(this.cameraCtr.camera.matrixWorld).invert());
        this.trsMat.multiplyMatrices(this.bindTarget.matrixWorld,this.locCam);
        this.cameraCtr.camera.applyMatrix4(this.trsMat);
        this.tV0.copy(this.tarVec);
        this.cameraCtr.target.copy(this.tV0.applyMatrix4(this.bindTarget.matrixWorld));
        if(this.customCall)this.customCall();
    }

}